#ifndef _KTV_MESSAGE_H_
#define _KTV_MESSAGE_H_

#include "ui_point.h"
#include "ui_rect.h"
#include "SDL/SDL.h"
#include <string>


namespace UI
{

class UI_MessageClient;
class UI_Message
{
public:
	enum EMessageType
	{
		UNKNOWN = 0,  //!< An unknown message, this is not a valid type
		APP_DESTROY_FRAME,	//!< CMessage used to delete frame objects, where Source() is the frame that is to be deleted, Destination() should be 0
		APP_EXIT,  //!< CMessage used to tell controls or windows that the application is closing
		APP_PAINT,	//!< CMessage used to tell controls or windows to redraw themselves
		CTRL_DOUBLELCLICK,	//!< TIntMessage generated when a control is double clicked with the left mouse button
		CTRL_DOUBLEMCLICK,	//!< TIntMessage generated when a control is double clicked with the middle mouse button
		CTRL_DOUBLERCLICK,	//!< TIntMessage generated when a control is double clicked with the right mouse button
		CTRL_GAININGKEYFOCUS,  //!< CMessage used to tell a control that it's getting the keyboard focus
		CTRL_GAININGMOUSEFOCUS,  //!< CMessage used to tell a control that it's getting the mouse focus
		CTRL_LOSINGKEYFOCUS,  //!< CMessage used to tell a control that it's losing the keyboard focus
		CTRL_LOSINGMOUSEFOCUS,	//!< CMessage used to tell a control that it's losing the mouse focus
		CTRL_MESSAGEBOXRETURN,	//!< CValueMessage sent when a CMessageBox closes
		CTRL_RESIZE,  //!< TPointMessage used to tell the app that the view has been resized
		CTRL_SINGLELCLICK,	//!< TIntMessage generated when a control is clicked on with the left mouse button
		CTRL_SINGLEMCLICK,	//!< TIntMessage generated when a control is clicked on with the middle mouse button
		CTRL_SINGLERCLICK,	//!< TIntMessage generated when a control is clicked on with the right mouse button
		CTRL_TIMER, //!< TIntMessage used to tell when a timer has expired, where Value() is the count of times fired
		CTRL_VALUECHANGE,  //!< CValueMessage generated when a control's text or value is changed via user input
		CTRL_VALUECHANGING,  //!< CValueMessage generated when a control's text or value is in the process of changing via user input
		KEYBOARD_KEYDOWN,  //!< CKeyboardMessage generated when a keyboard key is pressed
		KEYBOARD_KEYUP,  //!< CKeyboardMessage generated when a keyboard key is released
		MOUSE_BUTTONDOWN,  //!< CMouseMessage generated when a mouse button is pressed
		MOUSE_BUTTONUP,  //!< CMouseMessage generated when a mouse button is released
		MOUSE_MOVE,  //!< CMouseMessage generated when a mouse is moved
		SDL,  //!< An unhandled SDL event
		USER  //!< Any user defined messages of type CUserMessage
	};
	UI_Message(const EMessageType MessageType, const UI_MessageClient* pDestination, const UI_MessageClient* pSource);
	virtual ~UI_Message(void) { }
	const EMessageType MessageType(void) { return m_MessageType; }
	const UI_MessageClient* Destination(void) { return m_pDestination; }
	const UI_MessageClient* Source(void) { return m_pSource; }
protected:
	const EMessageType m_MessageType;
	const UI_MessageClient* m_pDestination;
	const UI_MessageClient* m_pSource;

private:
	void operator=(UI_Message) { }
};

class UI_SDLMessage : public UI_Message
{
public:
	UI_SDLMessage(const EMessageType MessageType, const UI_MessageClient* pDestination, const UI_MessageClient* pSource, SDL_Event SDLEvent);

	SDL_Event SDLEvent;
};

class UI_KeyboardMessage : public UI_Message
{
public:
	UI_KeyboardMessage(const EMessageType MessageType, const UI_MessageClient* pDestination, const UI_MessageClient* pSource,
		unsigned char ScanCode, SDLMod Modifiers, SDLKey Key, Uint16 Unicode);

	unsigned char ScanCode;
	SDLMod Modifiers;
	SDLKey Key;
	Uint16 Unicode;
};


class UI_MouseMessage : public UI_Message
{
public:
	enum EMouseButton
	{
		NONE = 0,				//!< No mouse button
		LEFT = 1,				//!< The left mouse button
		RIGHT = 2,			//!< The right mouse button
		MIDDLE = 4,			//!< The middle mouse button
		WHEELUP = 8,		//!< The mouse wheel moved up
		WHEELDOWN = 16	//!< The mouse wheel moved down
	};
	UI_MouseMessage(const EMessageType MessageType, const UI_MessageClient* pDestination, const UI_MessageClient* pSource,
		UI_Point Point, UI_Point Relative, unsigned int Button);
	static unsigned int TranslateSDLButton(Uint8 SDLButton);
	static unsigned int TranslateSDLButtonState(Uint8 SDLButtonState);
	UI_Point Point;
	UI_Point Relative;
	unsigned int Button;
};

template<typename T>
class UI_ValueMessage : public UI_Message
{
public:
	UI_ValueMessage(const EMessageType MessageType, const UI_MessageClient* pDestination, const UI_MessageClient* pSource, const T& Value ) :
		UI_Message(MessageType, pDestination, pSource),
		m_Value(Value)
	{ }
	const T& Value(void) { return m_Value; }
	void SetValue(const T& Value) { m_Value = Value; }
protected:
	T m_Value;
};
typedef UI_ValueMessage<int> TIntMessage;
typedef UI_ValueMessage<float> TFloatMessage;
typedef UI_ValueMessage<double> TDoubleMessage;
typedef UI_ValueMessage<std::string> TStringMessage;
typedef UI_ValueMessage<UI_Point> TPointMessage;
typedef UI_ValueMessage<UI_Rect> TRectMessage;
class UI_Window;
typedef UI_ValueMessage<UI_Window*> TChangeUIMessage;

}



#endif // _KTV_MESSAGE_H_

